package format;

import java.io.BufferedReader;
import java.io.FileReader;

import oracle.TraitFormatOracle;
import test.TestTraitFormat;

import file.FileComparator;
import file.PersistenceFile;


public class TraitFormat {

	private static final char ESPACE	= 'b';
	private static final char RC 		= System.getProperty("line.separator").charAt(0);
	private static final char ERROR 	= 'f';
	private static final char HEXA 		= 'h';
	
	public Format traitFormat(final String input) {
		// CODE
		int typeFormat = -1;
		char c;
		int etat = 1;
		char event;
		
		String toHexa = input + RC;
		
		for (int i = 0; i < toHexa.length() && typeFormat == -1; i++) {
			
			c = toHexa.charAt(i);		
			event = getEvent(c);
			
			switch (etat) {
			case 1:
				if(event == HEXA) {
					etat = 2;
				}
				else {
					typeFormat = 0;
				}
				break;
			case 2:
				if(event == HEXA) {
					etat = 3;
				}
				else {
					typeFormat = 0;
				}
				break;
			case 3:
				if(event == HEXA) {
					etat = 5;
				}
				else if (event == RC){
					typeFormat = 1;
				}
				else if (event == ESPACE){
					etat = 6;
				}
				else {
					typeFormat = 0;
				}
				break;
			case 5:
				if(event == HEXA) {
					etat = 7;
				} 
				else {
					typeFormat = 0;
				}
				break;
			case 6:
				if(event == HEXA) {
					etat = 9;
				} 
				else {
					typeFormat = 0;
				}
				
				break;
			case 7:
				if(event == RC) {
					typeFormat = 2;
				} 
				else {
					typeFormat = 0;
				}
				break;
			case 9:
				if(event == HEXA) {
					etat = 10;
				} 
				else {
					typeFormat = 0;
				}
				break;
			case 10:
				if(event == RC) {
					typeFormat = 3;
				} 
				else {
					typeFormat = 0;
				}
				break;
			default:
				typeFormat = 0;
				break;
			}			
		}
		Format format = null;
		if(typeFormat == 0) {
			int[] tab = {-1,-1};
			format = new Format(typeFormat, tab, input);
		} 
		else {
			format = new Format(typeFormat, hexaToInt(input, typeFormat), input);
		}
		
		return format;
	}
	
	private static boolean isHexa(char c) {
		
		if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
			return true;
		}
		
		return false;
	}
	
	private static char getEvent(char c) {
		if(isHexa(c)) {
			return HEXA;
		}
		else if (c == ' ') {
			return ESPACE;
		}
		else if (c == RC) {
			return RC;
		}
		else {
			return ERROR;
		}
		
	}
	
	private static int[] hexaToInt(String input, int noFormat) {
		assert (noFormat == 1 || noFormat == 2 || noFormat == 3);
		
		String[] split = null;
		
		switch (noFormat) {
		case 1 :
		case 3 :
			split = input.split(" ");
			break;
		case 2 :
			split = new String[2];
			split[0] = input.substring(0,2);
			split[1] = input.substring(2,4);
		}
		
		int[] hexTab = {-1,-1};
		
		for (int i=0; i<split.length; ++i) {
			hexTab[i] = Integer.parseInt(split[i], 16);
		}

		return hexTab;
	}
	
	public static void autoTest(final String jdtFile, final String resFile) {
		// Test the JDT and create RUN file
		String runFile = jdtFile.substring(0, jdtFile.length() - 3) + "run";
		TestTraitFormat.testTraitFormat(jdtFile, runFile);
		
		// Test the RUN File with the Oracle
		String oracleFile = jdtFile.substring(0, jdtFile.length() - 3) + "orc";
		
		StringBuffer sb = new StringBuffer();
		
		try {
			BufferedReader reader = new BufferedReader(new FileReader(runFile));
			String inputNo;
			String inputTmp;
			String input;
			Format format = null;
			
			while (((input = reader.readLine()) != null)) {
				int i = 0;
				
				// noTest
				inputNo = "";
				for (; i<input.length() && input.charAt(i) != ' '; ++i) {
					inputNo += input.charAt(i);
				}
				
				// inputTest
				inputTmp = "";
				++i;
				for (; i<input.length(); ++i) {
					inputTmp += input.charAt(i);
				}
				
				try {
					format = Format.getFormatByString(inputTmp);
				}
				catch(InvalidFormatException e) {
					format = Format.defaultFormat;
				}
				
				sb.append(String.valueOf(inputNo));
				sb.append(" ");
				sb.append(TraitFormatOracle.oracle(format));
				sb.append(PersistenceFile.LINE_SEPARATOR);
			}
		}
		catch (Exception e) {
			
		}
		
		PersistenceFile.stringToFile(oracleFile, sb.toString());
		
		// File comparaison between JDT and Oracle files
		// and create resFile
		FileComparator.compare(jdtFile, oracleFile, resFile);
	}
	
}
